package com.wushijia.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

/**
 * description:使用EnableWebSecurity注解开启权限验证，并做相关配置
 *
 * @author yang
 * @date 2018/11/13 10:21
 */
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private UserDetailsService customizeUserDetailsServiceImpl;

  @Bean
  DaoAuthenticationProvider daoAuthenticationProvider() {
    DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
    daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
    daoAuthenticationProvider.setUserDetailsService(customizeUserDetailsServiceImpl);
    return daoAuthenticationProvider;
  }

  @Bean
  public BCryptPasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

//  @Bean
//  PasswordEncoder passwordEncoder(){
//    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
//  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//    //内存中添加加密用户
//    auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
//        .withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123456")).roles("client");
//    //以下两种写法等价
    //auth.userDetailsService(customizeUserDetailsServiceImpl).passwordEncoder(passwordEncoder());
    auth.authenticationProvider(daoAuthenticationProvider());
  }

  //==============================非数据库配置
 /* @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user_1").password("123456").authorities("USER")
        .and()
        .withUser("user_2").password("123456").authorities("USER");
  }*/
  //======================================================================

  /**
   * 这一步的配置是必不可少的，否则SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
   */
  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  /**
   * description:需要保护/oauth/authorize以及/oauth/confirm_access这两个endpoint，当然主要是/oauth/authorize这个。把整个/oauth/**保护进来
   * 由于其他几个/oauth/开头的认证endpoint配置的认证优先级高于默认的WebSecurityConfigurerAdapter配置(order=100)，因此默认的可以这样配置
   *
   * @author yang
   * @date 2019/1/23 11:30
   */
  @Override
  protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http.csrf().disable();
    http
        .requestMatchers().antMatchers("/oauth/**", "/login/**", "/logout/**")
        .and()
        .authorizeRequests()
        .antMatchers("/oauth/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin().permitAll(); //新增login form支持用户登录及授权
    // @formatter:on
  }
}
